home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / CMD.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  23KB  |  930 lines

  1. /*    SCCS Id: @(#)cmd.c    3.0    89/11/15
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"
  6. #include    "func_tab.h"
  7.  
  8. #ifdef DUMB    /* stuff commented out in extern.h, but needed here */
  9. extern int NDECL(doapply); /**/
  10. extern int NDECL(dorub); /**/
  11. extern int NDECL(dojump); /**/
  12. extern int NDECL(doextlist); /**/
  13. extern int NDECL(dodrop); /**/
  14. extern int NDECL(doddrop); /**/
  15. extern int NDECL(dodown); /**/
  16. extern int NDECL(doup); /**/
  17. extern int NDECL(donull); /**/
  18. extern int NDECL(dowipe); /**/
  19. extern int NDECL(do_mname); /**/
  20. extern int NDECL(ddocall); /**/
  21. extern int NDECL(dotakeoff); /**/
  22. extern int NDECL(doremring); /**/
  23. extern int NDECL(dowear); /**/
  24. extern int NDECL(doputon); /**/
  25. extern int NDECL(doddoremarm); /**/
  26. extern int NDECL(dokick); /**/
  27. extern int NDECL(dothrow); /**/
  28. extern int NDECL(doeat); /**/
  29. extern int NDECL(done2); /**/
  30. extern int NDECL(doengrave); /**/
  31. extern int NDECL(dopickup); /**/
  32. extern int NDECL(ddoinv); /**/
  33. extern int NDECL(dotypeinv); /**/
  34. extern int NDECL(dolook); /**/
  35. extern int NDECL(doprgold); /**/
  36. extern int NDECL(doprwep); /**/
  37. extern int NDECL(doprarm); /**/
  38. extern int NDECL(doprring); /**/
  39. extern int NDECL(dopramulet); /**/
  40. extern int NDECL(doprtool); /**/
  41. extern int NDECL(dosuspend); /**/
  42. extern int NDECL(doforce); /**/
  43. extern int NDECL(doopen); /**/
  44. extern int NDECL(doclose); /**/
  45. extern int NDECL(dosh); /**/
  46. extern int NDECL(dodiscovered); /**/
  47. extern int NDECL(doset); /**/
  48. extern int NDECL(dotogglepickup); /**/
  49. extern int NDECL(dowhatis); /**/
  50. extern int NDECL(dowhatdoes); /**/
  51. extern int NDECL(dohelp); /**/
  52. extern int NDECL(dohistory); /**/
  53. extern int NDECL(doloot); /**/
  54. extern int NDECL(dodrink); /**/
  55. extern int NDECL(dodip); /**/
  56. extern int NDECL(dosacrifice); /**/
  57. extern int NDECL(dopray); /**/
  58. extern int NDECL(doturn); /**/
  59. extern int NDECL(doredraw); /**/
  60. extern int NDECL(doread); /**/
  61. extern int NDECL(dosave); /**/
  62. extern int NDECL(dosave0); /**/
  63. extern int NDECL(dosearch); /**/
  64. extern int FDECL(dosearch0, (int)); /**/
  65. extern int NDECL(doidtrap); /**/
  66. extern int NDECL(dopay); /**/
  67. extern int NDECL(dosit); /**/
  68. extern int NDECL(dotalk); /**/
  69. extern int NDECL(docast); /**/
  70. extern int NDECL(dovspell); /**/
  71. extern int NDECL(doredotopl); /**/
  72. extern int NDECL(dotele); /**/
  73. extern int NDECL(dountrap); /**/
  74. extern int NDECL(doversion); /**/
  75. extern int NDECL(doextversion); /**/
  76. extern int NDECL(dowield); /**/
  77. extern int NDECL(dozap); /**/
  78. #endif /* DUMB */
  79.  
  80. #ifdef OVL1
  81.  
  82. static int NDECL((*timed_occ_fn));
  83.  
  84. #endif /* OVL1 */
  85.  
  86. STATIC_PTR int NDECL(timed_occupation);
  87. STATIC_PTR int NDECL(doextcmd);
  88. # ifdef POLYSELF
  89. STATIC_PTR int NDECL(domonability);
  90. # endif
  91. # ifdef WIZARD
  92. STATIC_PTR int NDECL(wiz_wish);
  93. STATIC_PTR int NDECL(wiz_identify);
  94. STATIC_PTR int NDECL(wiz_map);
  95. STATIC_PTR int NDECL(wiz_genesis);
  96. STATIC_PTR int NDECL(wiz_where);
  97. STATIC_PTR int NDECL(wiz_detect);
  98. STATIC_PTR int NDECL(wiz_level_tele);
  99. # endif
  100. # ifdef EXPLORE_MODE
  101. STATIC_PTR int NDECL(enter_explore_mode);
  102. # endif
  103. # if defined(WIZARD) || defined(EXPLORE_MODE)
  104. STATIC_PTR int NDECL(wiz_attributes);
  105. # endif
  106.  
  107. #ifdef STUPID_CPP
  108. static char FDECL(unctrl, (CHAR_P));
  109. static char FDECL(unmeta, (CHAR_P));
  110. #endif
  111.  
  112. #ifdef OVL1
  113.  
  114. /* Count down by decrementing multi */
  115. STATIC_PTR int
  116. timed_occupation() {
  117.     (*timed_occ_fn)();
  118.     if (multi > 0)
  119.         multi--;
  120.     return multi > 0;
  121. }
  122.  
  123. /* If you have moved since initially setting some occupations, they
  124.  * now shouldn't be able to restart.
  125.  *
  126.  * The basic rule is that if you are carrying it, you can continue
  127.  * since it is with you.  If you are acting on something at a distance,
  128.  * your orientation to it must have changed when you moved.
  129.  *
  130.  * The exception to this is taking off items, since they can be taken
  131.  * off in a number of ways in the intervening time, screwing up ordering.
  132.  *
  133.  *    Currently:    Take off all armor.
  134.  *            Picking Locks / Forcing Chests.
  135.  */
  136. void
  137. reset_occupations() {
  138.  
  139.     reset_remarm();
  140.     reset_pick();
  141. }
  142.  
  143. /* If a time is given, use it to timeout this function, otherwise the
  144.  * function times out by its own means.
  145.  */
  146. void
  147. set_occupation(fn, txt, xtime)
  148. int NDECL((*fn));
  149. const char *txt;
  150. int xtime;
  151. {
  152.     if (xtime) {
  153.         occupation = timed_occupation;
  154.         timed_occ_fn = fn;
  155.     } else
  156.         occupation = fn;
  157.     occtxt = txt;
  158.     occtime = 0;
  159.     return;
  160. }
  161.  
  162. #ifdef REDO
  163.  
  164. static char NDECL(popch);
  165.  
  166. /* Provide a means to redo the last command.  The flag `in_doagain' is set
  167.  * to true while redoing the command.  This flag is tested in commands that
  168.  * require additional input (like `throw' which requires a thing and a
  169.  * direction), and the input prompt is not shown.  Also, while in_doagain is
  170.  * TRUE, no keystrokes can be saved into the saveq.
  171.  */
  172. #define BSIZE 20
  173. static char pushq[BSIZE], saveq[BSIZE];
  174. static int NEARDATA phead, NEARDATA ptail, NEARDATA shead, NEARDATA stail;
  175.  
  176. static char
  177. popch() {
  178.     /* If occupied, return 0, letting tgetch know a character should
  179.      * be read from the keyboard.  If the character read is not the
  180.      * ABORT character (as checked in pcmain.c), that character will be
  181.      * pushed back on the pushq.
  182.      */
  183.     if (occupation) return 0;
  184.     if (in_doagain) return (shead != stail) ? saveq[stail++] : 0;
  185.     else        return (phead != ptail) ? pushq[ptail++] : 0;
  186. }
  187.  
  188. char
  189. pgetchar() {        /* curtesy of aeb@cwi.nl */
  190.     register int ch;
  191.  
  192.     if(!(ch = popch()))
  193.         ch = tgetch();
  194.     return(ch);
  195. }
  196.  
  197. /* A ch == 0 resets the pushq */
  198. void
  199. pushch(ch)
  200. char ch;
  201. {
  202.     if (!ch)
  203.         phead = ptail = 0;
  204.     if (phead < BSIZE)
  205.         pushq[phead++] = ch;
  206.     return;
  207. }
  208.  
  209. /* A ch == 0 resets the saveq.    Only save keystrokes when not
  210.  * replaying a previous command.
  211.  */
  212. void
  213. savech(ch)
  214. char ch;
  215. {
  216.     if (!in_doagain) {
  217.         if (!ch)
  218.             phead = ptail = shead = stail = 0;
  219.         else if (shead < BSIZE)
  220.             saveq[shead++] = ch;
  221.     }
  222.     return;
  223. }
  224. #endif /* REDO */
  225.  
  226. #endif /* OVL1 */
  227. #ifdef OVLB
  228.  
  229. STATIC_PTR int
  230. doextcmd()    /* here after # - now read a full-word command */
  231. {
  232.     char buf[BUFSZ];
  233.     register const struct ext_func_tab *efp = extcmdlist;
  234. again:
  235.     pline("# ");
  236. #ifdef COM_COMPL
  237.     get_ext_cmd(buf);
  238. #else
  239.     getlin(buf);
  240. #endif
  241.     clrlin();
  242.     if(buf[0] == '\0' || buf[0] == '\033')
  243.         return 0;
  244.     if(buf[0] == '?') {
  245.         (void) doextlist();
  246.         goto again;
  247.     }
  248.     while(efp->ef_txt) {
  249.         if(!strcmp(efp->ef_txt, buf))
  250.             return (*(efp->ef_funct))();
  251.         efp++;
  252.     }
  253.     pline("%s: unknown extended command.", buf);
  254.     return 0;
  255. }
  256.  
  257. int
  258. doextlist()    /* here after #? - now list all full-word commands */
  259. {
  260.     register const struct ext_func_tab *efp = extcmdlist;
  261.     char     buf[BUFSZ];
  262.  
  263.     set_pager(0);
  264.     if(page_line("") ||
  265.        page_line("            Extended Commands List") ||
  266.        page_line("") ||
  267.        page_line("    Press '#', then type (first letter only):") ||
  268.        page_line(""))                                        goto quit;
  269.  
  270.     while(efp->ef_txt) {
  271.  
  272.         Sprintf(buf, "    %-8s  - %s.", efp->ef_txt, efp->ef_desc);
  273.         if(page_line(buf)) goto quit;
  274.         efp++;
  275.     }
  276.     set_pager(1);
  277.     return 0;
  278. quit:
  279.     set_pager(2);
  280.     return 0;
  281. }
  282.  
  283. #ifdef POLYSELF
  284. STATIC_PTR int
  285. domonability()
  286. {
  287.     if (can_breathe(uasmon)) return dobreathe();
  288.     else if (attacktype(uasmon, AT_SPIT)) return dospit();
  289.     else if (u.usym == S_NYMPH) return doremove();
  290.     else if (u.usym == S_UMBER) return doconfuse();
  291.     else if (is_were(uasmon)) return dosummon();
  292.     else if (webmaker(uasmon)) return dospinweb();
  293.     else if (is_hider(uasmon)) return dohide();
  294.     else if (u.usym == S_UNICORN) return use_unicorn_horn((struct obj *)0);
  295.     else if (u.umonnum >= 0)
  296.         pline("Any special ability you may have is purely reflexive.");
  297.     else You("don't have a special ability!");
  298.     return 0;
  299. }
  300. #endif
  301.  
  302. #ifdef EXPLORE_MODE
  303. STATIC_PTR int
  304. enter_explore_mode()
  305. {
  306.     if(!discover && !wizard) {
  307.         pline("Beware!  From discovery mode there will be no return to normal game.");
  308.         more();
  309. #ifndef MACOS
  310.         pline("Do you want to enter discovery mode? ");
  311.          if(yn() == 'y') {
  312. #else
  313.         if(!flags.silent) SysBeep(1);
  314.         if(UseMacAlertText(128, "Enter discovery mode ?") == 1) {
  315. #endif
  316.             clrlin();
  317.             pline("You are now in non-scoring discovery mode.");
  318.             discover = TRUE;
  319.         }
  320.         else {
  321.             clrlin();
  322.             pline("Resuming normal game.");
  323.         }
  324.     }
  325.     return 0;
  326. }
  327. #endif
  328.  
  329. #ifdef WIZARD
  330. STATIC_PTR int
  331. wiz_wish()    /* Unlimited wishes for wizard mode by Paul Polderman */
  332. {
  333.     if (wizard)    makewish();
  334.     else        pline("Unavailable command '^W'.");
  335.     return 0;
  336. }
  337.  
  338. STATIC_PTR int
  339. wiz_identify()
  340. {
  341.     struct obj *obj;
  342.  
  343.     if (!wizard)
  344.         pline("Unavailable command '^I'.");
  345.     else {
  346.         for (obj = invent; obj; obj = obj->nobj)
  347.             if (!objects[obj->otyp].oc_name_known || !obj->known
  348.                         || !obj->dknown || !obj->bknown)
  349.                 (void) identify(obj);
  350.     }
  351.     return 0;
  352. }
  353.  
  354. STATIC_PTR int
  355. wiz_map()
  356. {
  357.     if (wizard)    do_mapping();
  358.     else        pline("Unavailable command '^F'.");
  359.     return 0;
  360. }
  361.  
  362. STATIC_PTR int
  363. wiz_genesis()
  364. {
  365.     if (wizard)    (void) create_particular();
  366.     else        pline("Unavailable command '^G'.");
  367.     return 0;
  368. }
  369.  
  370. STATIC_PTR int
  371. wiz_where()
  372. {
  373.     if (wizard) {
  374.         pline("Medusa:%d  Wiz:%d  Big:%d", medusa_level, wiz_level, bigroom_level);
  375. #ifdef STRONGHOLD
  376. #  ifdef MUSIC
  377.         pline("Castle:%d (tune %s)  Tower:%d-%d",
  378.               stronghold_level, tune, tower_level, tower_level+2);
  379. #  else
  380.         pline("Castle:%d  Tower:%d-%d",
  381.               stronghold_level, tower_level, tower_level+2);
  382. #  endif
  383. #endif
  384. #ifdef REINCARNATION
  385.         pline("Rogue:%d", rogue_level);
  386. #endif
  387. #ifdef ORACLE
  388.         pline("Oracle:%d", oracle_level);
  389. #endif
  390.     }
  391.     else    pline("Unavailable command '^O'.");
  392.     return 0;
  393. }
  394.  
  395. STATIC_PTR int
  396. wiz_detect()
  397. {
  398.     if(wizard)  (void) findit();
  399.     else        pline("Unavailable command '^E'.");
  400.     return 0;
  401. }
  402.  
  403. STATIC_PTR int
  404. wiz_level_tele()
  405. {
  406.     if (wizard)    level_tele();
  407.     else        pline("Unavailable command '^V'.");
  408.     return 0;
  409. }
  410.  
  411. #endif /* WIZARD */
  412.  
  413. void
  414. enlightenment() {
  415.     char buf[BUFSZ];
  416.  
  417.     cornline(0, "Current Attributes:");
  418.  
  419.     if (u.ualign == 0) cornline(1, "You are nominally aligned.");
  420.     else if (u.ualign > 3) cornline(1, "You are stridently aligned.");
  421.     else if (u.ualign > 0) cornline(1, "You are haltingly aligned.");
  422.     else cornline(1, "You have strayed.");
  423. #ifdef WIZARD
  424.     if (wizard) {
  425.         Sprintf(buf, "Your alignment is %d.", u.ualign);
  426.         cornline(1, buf);
  427.     }
  428. #endif
  429.  
  430.     if (Adornment) cornline(1, "You are adorned.");
  431.     if (Teleportation) cornline(1, "You can teleport.");
  432.     if (Regeneration) cornline(1, "You regenerate.");
  433.     if (Searching) cornline(1, "You have automatic searching.");
  434.     if (See_invisible) cornline(1, "You see invisible.");
  435.     if (Stealth) cornline(1, "You are stealthy.");
  436.     if (Levitation) cornline(1, "You are levitating.");
  437.     if (Hunger) cornline(1, "You have hunger.");
  438.     if (Aggravate_monster) cornline(1, "You aggravate monsters.");
  439.     if (Poison_resistance) cornline(1, "You are poison resistant.");
  440.     if (Fire_resistance) cornline(1, "You are fire resistant.");
  441.     if (Cold_resistance) cornline(1, "You are cold resistant.");
  442.     if (Shock_resistance) cornline(1, "You are shock resistant.");
  443.     if (Sleep_resistance) cornline(1, "You are sleep resistant.");
  444.     if (Disint_resistance) cornline(1, "You are disintegration-resistant.");
  445.     if (Protection_from_shape_changers)
  446.         cornline(1, "You are protected from shape changers.");
  447.     if (Conflict) cornline(1, "You cause conflict.");
  448.     if (Protection) cornline(1, "You are protected.");
  449.     if (Warning) cornline(1, "You are warned.");
  450.     if (Teleport_control) cornline(1, "You have teleport control.");
  451. #ifdef POLYSELF
  452.     if (Polymorph) cornline(1, "You are polymorphing.");
  453.     if (Polymorph_control) cornline(1, "You have polymorph control.");
  454. #endif
  455.     if (Telepat) cornline(1, "You are telepathic.");
  456.     if (Fast) cornline(1, "You are fast.");
  457.     /* if (Stunned) cornline(1, "You are stunned."); */
  458.     /* if (Confusion) cornline(1, "You are confused."); */
  459.     /* if (Sick) cornline(1, "You are sick."); */
  460.     /* if (Blinded) cornline(1, "You are blinded."); */
  461.     if (Invisible) cornline(1, "You are invisible.");
  462.     else if (Invis) cornline(1, "You are invisible to others.");
  463.     if (Wounded_legs) {
  464.         Sprintf(buf, "You have wounded %s.",
  465.                         makeplural(body_part(LEG)));
  466.         cornline(1, buf);
  467.     }
  468.     if (Stoned) cornline(1, "You are turning to stone.");
  469.     /* if (Hallucination) cornline(1, "You are hallucinating."); */
  470.     if (Glib) {
  471.         Sprintf(buf, "You have slippery %s.",
  472.                         makeplural(body_part(FINGER)));
  473.         cornline(1, buf);
  474.     }
  475.     if (Reflecting) cornline(1, "You have reflection.");
  476.     if (Strangled) cornline(1, "You are being strangled.");
  477.     if (Lifesaved) cornline(1, "Your life will be saved.");
  478.     if (Fumbling) cornline(1, "You fumble.");
  479.     if (Jumping) cornline(1, "You can jump.");
  480.     if (Wwalking) cornline(1, "You can walk on water.");
  481.     if (Antimagic) cornline(1, "You are magic-protected.");
  482.     if (Displaced) cornline(1, "You are displaced.");
  483.     if (Clairvoyant) cornline(1, "You are clairvoyant.");
  484.     if (stone_luck(TRUE) > 0) cornline(1, "You have extra luck.");
  485.     if (stone_luck(TRUE) < 0) cornline(1, "You have reduced luck.");
  486.     if (carrying(LUCKSTONE)) {
  487.         if (stone_luck(FALSE) <= 0)
  488.             cornline(1, "Bad luck does not time out for you.");
  489.         if (stone_luck(FALSE) >= 0)
  490.             cornline(1, "Good luck does not time out for you.");
  491.     }
  492. #ifdef WIZARD
  493.     if (wizard) {
  494.         Sprintf(buf, "Your luck is %d.", Luck);
  495.         cornline(1, buf);
  496.     }
  497. #endif
  498.  
  499.     cornline(2, "");
  500.     return;
  501. }
  502.  
  503. #if defined(WIZARD) || defined(EXPLORE_MODE)
  504. STATIC_PTR int
  505. wiz_attributes()
  506. {
  507.     if (wizard || discover)
  508.         enlightenment();
  509.     else
  510.         pline("Unavailable command '^X'.");
  511.     return 0;
  512. }
  513. #endif /* WIZARD || EXPLORE_MODE */
  514.  
  515. #endif /* OVLB */
  516. #ifdef OVL1
  517.  
  518. #ifndef M
  519. #define M(c)        (0x80 | (c))
  520. #endif
  521. #ifndef C
  522. #define C(c)        (0x1f & (c))
  523. #endif
  524. const struct func_tab cmdlist[]={
  525.     {C('d'), dokick},    /* "D" is for door!...? */
  526. #ifdef WIZARD
  527.     {C('e'), wiz_detect},
  528.     {C('f'), wiz_map},
  529.     {C('g'), wiz_genesis},
  530.     {C('i'), wiz_identify},
  531.     {C('o'), wiz_where},
  532. #endif
  533.     {C('p'), doredotopl},
  534.     {C('r'), doredraw},
  535.     {C('t'), dotele},
  536. #ifdef WIZARD
  537.     {C('v'), wiz_level_tele},
  538.     {C('w'), wiz_wish},
  539. #endif
  540. #if defined(WIZARD) || defined(EXPLORE_MODE)
  541.     {C('x'), wiz_attributes},
  542. #endif
  543. #ifdef SUSPEND
  544.     {C('z'), dosuspend},
  545. #endif
  546.     {'a', doapply},
  547.     {'A', doddoremarm},
  548. /*    'b', 'B' : go sw */
  549.     {'c', doclose},
  550.     {'C', do_mname},
  551.     {M('c'), dotalk},
  552.     {'d', dodrop},
  553.     {'D', doddrop},
  554.     {M('d'), dodip},
  555.     {'e', doeat},
  556.     {'E', doengrave},
  557. /* Soon to be
  558.     {'f', dofight, "fighting"},
  559.     {'F', doFight, "fighting"},
  560.  */
  561.     {M('f'), doforce},
  562. /*    'g', 'G' : multiple go */
  563. /*    'h', 'H' : go west */
  564.     {'h', dohelp}, /* if number_pad is set */
  565.     {'i', ddoinv},
  566.     {'I', dotypeinv},        /* Robert Viduya */
  567. /*    'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
  568.     {'j', dojump}, /* if number_pad is on */
  569.     {M('j'), dojump},
  570.     {'k', dokick}, /* if number_pad is on */
  571.     {'l', doloot}, /* if number_pad is on */
  572.     {M('l'), doloot},
  573. /*    'n' prefixes a count if number_pad is on */
  574. #ifdef POLYSELF
  575.     {M('m'), domonability},
  576. #endif /* POLYSELF */
  577.     {'N', ddocall}, /* if number_pad is on */
  578.     {M('N'), ddocall},
  579.     {'o', doopen},
  580.     {'O', doset},
  581. #ifdef THEOLOGY
  582.     {M('o'), dosacrifice},
  583. #endif /* THEOLOGY */
  584.     {'p', dopay},
  585.     {'P', doputon},
  586. #ifdef THEOLOGY
  587.     {M('p'), dopray},
  588. #endif /* THEOLOGY */
  589.     {'q', dodrink},
  590.     {'Q', done2},
  591.     {'r', doread},
  592.     {'R', doremring},
  593.     {M('r'), dorub},
  594.     {'s', dosearch, "searching"},
  595.     {'S', dosave},
  596.     {M('s'), dosit},
  597.     {'t', dothrow},
  598.     {'T', dotakeoff},
  599.     {M('t'), doturn},
  600. /*    'u', 'U' : go ne */
  601.     {'u', dountrap}, /* if number_pad is on */
  602.     {M('u'), dountrap},
  603.     {'v', doversion},
  604.     {'V', dohistory},
  605.     {M('v'), doextversion},
  606.     {'w', dowield},
  607.     {'W', dowear},
  608.     {M('w'), dowipe},
  609. #ifdef SPELLS
  610.     {'x', dovspell},            /* Mike Stephenson */
  611. #endif
  612. #ifdef EXPLORE_MODE
  613.     {'X', enter_explore_mode},
  614. #endif
  615. /*    'y', 'Y' : go nw */
  616.     {'z', dozap},
  617. #ifdef SPELLS
  618.     {'Z', docast},
  619. #endif
  620.     {'<', doup},
  621.     {'>', dodown},
  622.     {'/', dowhatis},
  623.     {'&', dowhatdoes},
  624.     {'?', dohelp},
  625. #ifdef SHELL
  626.     {'!', dosh},
  627. #endif
  628.     {'.', donull, "waiting"},
  629.     {' ', donull, "waiting"},
  630.     {',', dopickup},
  631.     {':', dolook},
  632.     {'^', doidtrap},
  633.     {'\\', dodiscovered},        /* Robert Viduya */
  634.     {'@', dotogglepickup},
  635.     {WEAPON_SYM,  doprwep},
  636.     {ARMOR_SYM,  doprarm},
  637.     {RING_SYM,  doprring},
  638.     {AMULET_SYM, dopramulet},
  639.     {TOOL_SYM, doprtool},
  640.     {GOLD_SYM, doprgold},
  641. #ifdef SPELLS
  642.     {SPBOOK_SYM, dovspell},            /* Mike Stephenson */
  643. #endif
  644.     {'#', doextcmd},
  645.     {0,0,0}
  646. };
  647. #undef M
  648.  
  649. const struct ext_func_tab extcmdlist[] = {
  650.     "chat", "talk to someone", dotalk,    /* converse? */
  651.     "dip", "dip an object into something", dodip,
  652.     "force", "force a lock", doforce,
  653.     "jump", "jump to a location", dojump,
  654.     "loot", "loot a box on the floor", doloot,
  655. #ifdef POLYSELF
  656.     "monster", "use a monster's special ability", domonability,
  657. #endif
  658.     "name", "name an item or type of object", ddocall,
  659. #ifdef THEOLOGY
  660.     "offer", "offer a sacrifice to the gods", dosacrifice,
  661.     "pray", "pray to the gods for help", dopray,
  662. #endif
  663.     "rub", "rub a lamp", dorub,
  664.     "sit", "sit down", dosit,
  665.     "turn", "turn undead", doturn,
  666.     "untrap", "untrap something", dountrap,
  667.     "version", "print compile time options for this version of NetHack",
  668.         doextversion,
  669.     "wipe", "wipe off your face", dowipe,
  670.     "?", "get this list of extended commands", doextlist,
  671.     NULL, NULL, donull
  672. };
  673.  
  674. #ifdef STUPID_CPP
  675. static char
  676. unctrl(sym)
  677. char sym;
  678. {
  679.     return (sym >= C('a') && sym <= C('z')) ? sym + 0140 : sym;
  680. }
  681.  
  682. static char
  683. unmeta(sym)
  684. char sym;
  685. {
  686.     return (sym & 0x7f);
  687. }
  688. #else
  689. #define unctrl(c)    ((c) <= C('z') ? (0x60 | (c)) : (c))
  690. #define unmeta(c)    (0x7f & (c))
  691. #endif
  692.  
  693.  
  694. void
  695. rhack(cmd)
  696. register char *cmd;
  697. {
  698.     register const struct func_tab *tlist = cmdlist;
  699.     boolean firsttime = FALSE;
  700.     register int res;
  701.  
  702.     if(!cmd) {
  703.         firsttime = TRUE;
  704.         flags.nopick = 0;
  705.         cmd = parse();
  706.     }
  707.     if(*cmd == (char)033) {
  708.         flags.move = 0;
  709.         return;
  710.     }
  711. #ifdef REDO
  712.     if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
  713.         in_doagain = TRUE;
  714.         stail = 0;
  715.         rhack(NULL);    /* read and execute command */
  716.         in_doagain = FALSE;
  717.         return;
  718.     }
  719.     /* Special case of *cmd == ' ' handled better below */
  720.     if(!*cmd || *cmd == (char)0377) {
  721. #else
  722.     if(!*cmd || *cmd == (char)0377 || (flags.no_rest_on_space && *cmd == ' ')){
  723. #endif
  724.         bell();
  725.         flags.move = 0;
  726.         return;        /* probably we just had an interrupt */
  727.     }
  728.     if(movecmd(*cmd)) {
  729.     walk:
  730.         if(multi) flags.mv = 1;
  731.         domove();
  732.         return;
  733.     }
  734.     if(movecmd(flags.num_pad ? unmeta(*cmd) : lowc(*cmd))) {
  735.         flags.run = 1;
  736.     rush:
  737.         if(firsttime){
  738.             if(!multi) multi = COLNO;
  739.             u.last_str_turn = 0;
  740.         }
  741.         flags.mv = 1;
  742.         domove();
  743.         return;
  744.     }
  745.     if(*cmd == 'g' && movecmd(cmd[1])) {
  746.         flags.run = 2;
  747.         goto rush;
  748.     }
  749.     if(((*cmd == 'G' || (flags.num_pad && *cmd == '5')) && 
  750.         movecmd(lowc(cmd[1]))) || movecmd(unctrl(*cmd))) {
  751.         flags.run = 3;
  752.         goto rush;
  753.     }
  754.     if((*cmd == 'm' || (flags.num_pad & *cmd == '-')) &&
  755.         movecmd(cmd[1])) {
  756.         flags.run = 0;
  757.         flags.nopick = 1;
  758.         goto walk;
  759.     }
  760.     if(*cmd == 'M' && movecmd(lowc(cmd[1]))) {
  761.         flags.run = 1;
  762.         flags.nopick = 1;
  763.         goto rush;
  764.     }
  765.     if(flags.num_pad && *cmd == '0') {
  766.             (void)ddoinv();    /* A convenience borrowed from the PC */
  767.         flags.move = 0;
  768.         multi = 0;
  769.         return;
  770.     }
  771.     while(tlist->f_char) {
  772.         if((*cmd & 0xff) == (tlist->f_char & 0xff)){
  773.             /* Special case of *cmd == ' ' handled here */
  774.             if (*cmd == ' ' && flags.no_rest_on_space)
  775.                 break;
  776.  
  777.             /* Now control-A can stop lengthy commands */
  778.             /* in the PC version only -- use ^C-N otherwise */
  779.             if (tlist->f_text && !occupation && multi)
  780. #ifdef __GNULINT__
  781.                 set_occupation(tlist->f_funct,
  782.                         tlist->f_text, multi);
  783. #else
  784.                 set_occupation(((struct func_tab *)tlist)->f_funct,
  785.                     tlist->f_text, multi);
  786. #endif
  787.             res = (*(tlist->f_funct))();
  788.             if(!res) {
  789.                 flags.move = 0;
  790.                 multi = 0;
  791.             }
  792.             return;
  793.         }
  794.         tlist++;
  795.     }
  796.     { char expcmd[10];
  797.       register char *cp = expcmd;
  798.       while(*cmd && cp-expcmd < sizeof(expcmd)-2) {
  799.         if(*cmd >= 040 && *cmd < 0177)
  800.             *cp++ = *cmd++;
  801.         else if (*cmd & 0200) {
  802.             *cp++ = 'M';
  803.             *cp++ = '-';
  804.             *cp++ = *cmd++ &=~ 0200;
  805.         }
  806.         else {
  807.             *cp++ = '^';
  808.             *cp++ = *cmd++ ^ 0100;
  809.         }
  810.       }
  811.       *cp++ = 0;
  812.       pline("Unknown command '%s'.", expcmd);
  813.     }
  814.     multi = flags.move = 0;
  815.     return;
  816. }
  817.  
  818. char
  819. lowc(sym)
  820. char sym;
  821. {
  822.     return (sym >= 'A' && sym <= 'Z') ? sym+'a'-'A' : sym;
  823. }
  824.  
  825. /* 'rogue'-like direction commands */
  826. const char NEARDATA sdir[] = "hykulnjb><";
  827. const char NEARDATA ndir[] = "47896321><";
  828. const schar NEARDATA xdir[10] = { -1,-1, 0, 1, 1, 1, 0,-1, 0, 0 };
  829. const schar NEARDATA ydir[10] = {  0,-1,-1,-1, 0, 1, 1, 1, 0, 0 };
  830. const schar zdir[10] = {  0, 0, 0, 0, 0, 0, 0, 0, 1,-1 };
  831.  
  832. #ifdef WALKIES
  833. int
  834. xytod(x, y)    /* convert an x,y pair into a direction code */
  835. schar x, y;
  836. {
  837.     register int dd;
  838.  
  839.     for(dd = 0; dd < 8; dd++)
  840.         if(x == xdir[dd] && y == ydir[dd]) return dd;
  841.  
  842.     return -1;
  843. }
  844.  
  845. void
  846. dtoxy(cc,dd)    /* convert a direction code into an x,y pair */
  847. coord *cc;
  848. register int dd;
  849. {
  850.     cc->x = xdir[dd];
  851.     cc->y = ydir[dd];
  852.     return;
  853. }
  854. #endif /* WALKIES */
  855.  
  856. int
  857. movecmd(sym)    /* also sets u.dz, but returns false for <> */
  858. char sym;
  859. {
  860.     register const char *dp;
  861.     register const char *sdp = flags.num_pad ? ndir : sdir;
  862.  
  863.     u.dz = 0;
  864.     if(!(dp = index(sdp, sym))) return 0;
  865.     u.dx = xdir[dp-sdp];
  866.     u.dy = ydir[dp-sdp];
  867.     u.dz = zdir[dp-sdp];
  868. #ifdef POLYSELF
  869.     if (u.dx && u.dy && u.umonnum == PM_GRID_BUG) {
  870.         u.dx = u.dy = 0;
  871.         return 0;
  872.     }
  873. #endif
  874.     return !u.dz;
  875. }
  876.  
  877. int
  878. getdir(s)
  879. boolean s;
  880. {
  881.     char dirsym;
  882.  
  883. #ifdef REDO
  884.     if (!in_doagain)
  885. #endif
  886.         if(s) pline("In what direction? ");
  887.     dirsym = readchar();
  888. #ifdef REDO
  889.     savech(dirsym);
  890. #endif
  891.     if(dirsym == '.' || dirsym == 's')
  892.         u.dx = u.dy = u.dz = 0;
  893.     else if(!movecmd(dirsym) && !u.dz) {
  894.         if(!index(quitchars, dirsym))
  895.             pline("What a strange direction!");
  896.         return 0;
  897.     }
  898.     if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir();
  899.     return 1;
  900. }
  901.  
  902. #endif /* OVL1 */
  903. #ifdef OVLB
  904.  
  905. void
  906. confdir()
  907. {
  908.     register int x = 
  909. #ifdef POLYSELF
  910.         (u.umonnum == PM_GRID_BUG) ? 2*rn2(4) :
  911. #endif
  912.                             rn2(8);
  913.     u.dx = xdir[x];
  914.     u.dy = ydir[x];
  915.     return;
  916. }
  917.  
  918. #endif /* OVLB */
  919. #ifdef OVL0
  920.  
  921. int
  922. isok(x,y)
  923. register int x, y;
  924. {
  925.     /* x corresponds to curx, so x==1 is the first column. Ach. %% */
  926.     return x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1;
  927. }
  928.  
  929. #endif /* OVL0 */
  930.